package escalas;

import java.math.BigDecimal;
import java.util.*;

import colecciones.bloques.BloqueExec;
import colecciones.bloques.BloqueFn;
import colecciones.bloques.BloqueTest;

import colecciones.colecciones.MiColeccion;

import usuarios.Usuario;
import despegar.utiles.Fecha;
import facade.RegistroAsientosComprados;
import aerolineas.Aerolinea;
import asientos.ClaseDeAsiento;
import asientos.EstadosAsiento;
import asientos.UbicacionesAsiento;
import asientos.Vuelo;

public class Escala implements Vuelo {
	
	public List<Vuelo> listaVuelos = new ArrayList<Vuelo>();

	public List<Vuelo> getListaVuelos() {
		return listaVuelos;
	}

	public void setListaVuelos(List<Vuelo> listaVuelos) {
		this.listaVuelos = listaVuelos;
	}

	public void addVuelo(Vuelo unVuelo){
		this.listaVuelos.add(unVuelo);
	}
	public void removeVuelo(Vuelo unVuelo){
		this.listaVuelos.remove(unVuelo);
	}
	
	// Temps
	private Usuario unUsuarioTempParaBloques = null;
	private int unRecargoTempParaBloques = 0;

	@Override
	public BigDecimal getPrecio() {
		// TODO Auto-generated method stub

		MiColeccion<Vuelo> coleccionVuelos = new MiColeccion<Vuelo>();
		coleccionVuelos.addAll(listaVuelos);
		MiColeccion<BigDecimal> coleccionPrecios = coleccionVuelos
				.map(new BloqueFn<Vuelo, BigDecimal>() {
					@Override
					public BigDecimal fn(Vuelo unVuelo) {
						return unVuelo.getPrecio();
					}
				});

		return new BigDecimal(coleccionPrecios.sum());
	}

	@Override
	public boolean esSuperOferta() {
		// Si todos los vuelos cumplen:
		MiColeccion<Vuelo> coleccionVuelos = new MiColeccion<Vuelo>();
		coleccionVuelos.addAll(listaVuelos);

		return coleccionVuelos.all(new BloqueTest<Vuelo>() {
			@Override
			public boolean test(Vuelo unVuelo) {
				return unVuelo.esSuperOferta();
			}
		});

	}

	@Override
	public void recargarSegunUsuario(Usuario unUsuario, int unRecargo) {
		// Recargo cada vuelo segun usuario
		MiColeccion<Vuelo> coleccionVuelos = new MiColeccion<Vuelo>();
		coleccionVuelos.addAll(listaVuelos);
		unUsuarioTempParaBloques = unUsuario;
		unRecargoTempParaBloques = unRecargo;
		coleccionVuelos.forEach(new BloqueExec<Vuelo>() {
			@Override
			public void exec(Vuelo unVuelo) {
				if (!unUsuarioTempParaBloques.tieneCuentaPaga()) {
					unVuelo.setPrecio(unVuelo.getPrecio().add(
							new BigDecimal(unRecargoTempParaBloques)));
				}
			}
		});

	}

	@Override
	public String getOrigen() {
		// El origen del primer vuelo de la lista
		return listaVuelos.get(0).getOrigen();
	}

	@Override
	public String getDestino() {
		// El destino del ultimo vuelo de la lista
		return listaVuelos.get(listaVuelos.size() - 1).getDestino();
	}

	@Override
	public Fecha getFechaSalida() {
		// getFechaDeSalida del primer vuelo de la lista
		return listaVuelos.get(0).getFechaSalida();
	}

	@Override
	public Fecha getFechaLlegada() {
		// getFechaDeLlegada del ultimo vuelo de la lista
		return listaVuelos.get(listaVuelos.size() - 1).getFechaLlegada();
	}

	@Override
	public String getHoraSalida() {
		// getHoraDeSalida del primer vuelo de la lista
		return listaVuelos.get(0).getHoraSalida();
	}

	@Override
	public String getHoraLlegada() {
		// getHoraDeLlegada del ultimo vuelo de la lista
		return listaVuelos.get(listaVuelos.size() - 1).getHoraLlegada();
	}


	@Override
	public double getTiempoDeVuelo() {
		// Ultimo - Primero..
		// Lindo choclo quedo.. pero buen anda.. llega hasta el make it work..
		double tiempoVuelo = listaVuelos
				.get(listaVuelos.size() - 1)
				.getFechaLlegada()
				.plus(listaVuelos.get(listaVuelos.size() - 1)
						.getHoraLlegada())
				.diferenciaCon(
						listaVuelos.get(0).getFechaSalida()
								.plus(listaVuelos.get(0).getHoraSalida()));

		return tiempoVuelo;
	}


	/*
	 * En minutos
	 */
	public double getTiempoDeConexion() {
		// Sumatoria de todo los tiempos entre que llego de un vuelo y salgo del
		// siguiente.
		double tiempoConex = 0;

		for (int i = 1; i < this.listaVuelos.size(); i++) {
			tiempoConex += listaVuelos
					.get(i)
					.getFechaSalida()
					.plus(listaVuelos.get(i).getHoraSalida())
					.diferenciaCon(
							listaVuelos
									.get(i - 1)
									.getFechaLlegada()
									.plus(listaVuelos.get(i - 1)
											.getHoraLlegada()));
		}

		return tiempoConex;
	}

	@Override
	public void registrarCompra() {
		// Registrar todos los vuelos de la lista

		MiColeccion<Vuelo> coleccionVuelos = new MiColeccion<Vuelo>();
		coleccionVuelos.addAll(listaVuelos);

		coleccionVuelos.forEach(new BloqueExec<Vuelo>() {
			@Override
			public void exec(Vuelo unVuelo) {
				RegistroAsientosComprados.getInstance().registrarCompra(
						unVuelo.getCodigoDeVuelo());
			}
		});

	}

	@Override
	public String getCodigoDeVuelo() {
		// No deberia existir esto para escalas... puede ser mas de un vuelo!
		return null;
	}

	@Override
	public UbicacionesAsiento getUbicacion() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public ClaseDeAsiento getClase() {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public String getAerolinea() {
		return this.listaVuelos.get(0).getAerolinea();
	}
	@Override
	public boolean sosDeLaAerolinea(Aerolinea unaAerolinea) {
		return this.getAerolinea().equals(unaAerolinea);
	}

	@Override
	public double getPopularidad() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public List<String> getClasesDeAsientos() {
		MiColeccion<Vuelo> coleccionVuelos = new MiColeccion<Vuelo>();
		coleccionVuelos.addAll(listaVuelos);
		MiColeccion<String> coleccionClases = coleccionVuelos
				.map(new BloqueFn<Vuelo, String>() {
					@Override
					public String fn(Vuelo unVuelo) {
						return unVuelo.getClase().getNombre();
					}
				});
		
		return coleccionClases.asArrayList();
	}

	@Override
	public void reservar(final Usuario usuarioQueReserva) {
		MiColeccion<Vuelo> coleccionVuelos = new MiColeccion<Vuelo>();
		coleccionVuelos.addAll(listaVuelos);

		coleccionVuelos.forEach(new BloqueExec<Vuelo>() {
			@Override
			public void exec(Vuelo unVuelo) {
				unVuelo.reservar(usuarioQueReserva);
			}
		});
	}

	@Override
	public void comprar(final Usuario usuarioQueCompra) {
		MiColeccion<Vuelo> coleccionVuelos = new MiColeccion<Vuelo>();
		coleccionVuelos.addAll(listaVuelos);

		coleccionVuelos.forEach(new BloqueExec<Vuelo>() {
			@Override
			public void exec(Vuelo unVuelo) {
				unVuelo.comprar(usuarioQueCompra);
			}
		});
	}

	@Override
	public boolean estaLibre() {
		MiColeccion<Vuelo> coleccionVuelos = new MiColeccion<Vuelo>();
		coleccionVuelos.addAll(listaVuelos);

		return coleccionVuelos.all(new BloqueTest<Vuelo>() {
			@Override
			public boolean test(Vuelo unVuelo) {
				return unVuelo.getEstado().equals(EstadosAsiento.DISPONIBLE);
			}
		});
		 
	}

	@Override
	public EstadosAsiento getEstado() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setPrecio(BigDecimal precio) {
		// TODO Auto-generated method stub

	}

	@Override
	public Integer getNumeroDeAsiento() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void registrarReserva(String dniDelUsuarioQueReservo) {
		// TODO Auto-generated method stub
		
	}

}
